#include "videoext.h"


#include "palette.h"
#include "video.h"

extern long *pixels;
long *infopixels;

extern word *vRam;
extern word *fgRam;
extern word *bgRam;
extern signed long hScrollTable[];     //horizontal scrolling
extern long vScrollRam[];  

//user-created RAM
word *infotext;

struct rect
{
    int x;
    int y;
    int w;
    int h;
};

rect selections[5];
int curRegion=0;

void initVideoExt()
{
    initVideo();
   
    infotext=(word*)malloc(8192);
    infopixels=(long*)malloc(INFOWIDTH*INFOHEIGHT*sizeof(long));
}

extern bool disableFg;
extern bool disableBg;

void videoToSurfaceExt(SDL_Surface *surface)
{
    if (!disableBg) { bgTilesToPixelBuf(PRIORITY_LOW); }
    if (!disableFg) { fgTilesToPixelBuf(PRIORITY_LOW); }
    spritesToPixelBuf(PRIORITY_LOW);
    if (!disableBg) { bgTilesToPixelBuf(PRIORITY_HIGH); }
    if (!disableFg) { fgTilesToPixelBuf(PRIORITY_HIGH); }
    spritesToPixelBuf(PRIORITY_HIGH);
    textToPixelBuf();

    selectionsToPixelBuf();
    textToPixelBuf(infotext, infopixels, INFOWIDTH, INFOHEIGHT);

    pixelbuftosurfaceExt(surface);
}

void buftosurfaceExt(long *buf1, long *buf2, int w1, int w2, int wh, SDL_Surface *surface)
{
     int *pixels = (int *)surface->pixels;
 
     int pix=0;
     for (int h=0; h<wh; h++)
     {
         
         for (int lp=0; lp<w1; lp++) 
             pixels[pix++] = buf1[lp+(h*w1)]; 
         for (int lp2=0; lp2<w2; lp2++)
             pixels[pix++] = buf2[lp2+(h*w2)];
     }
}

void pixelbuftosurfaceExt(SDL_Surface *surface)
{
     
     buftosurfaceExt(pixels, infopixels, DISPLAYWIDTH, INFOWIDTH, WINDOWHEIGHT, surface);
     long clearColor = palColor2RGB(getfcRam(2,0));
     for (int lp=0; lp<DISPLAYSIZE; lp++)
         pixels[lp]=clearColor;
     for (int lp=0; lp<INFOSIZE; lp++)
         infopixels[lp]=clearColor;
}


void selectRegion(int x, int y, int w, int h)
{
    selections[curRegion].x = x;
    selections[curRegion].y = y;
    selections[curRegion].w = w;
    selections[curRegion].h = h;
}

#define EDGESIZE 1
#define MAXSELECTIONS 1
void selectionsToPixelBuf()
{
    for (int slp=0; slp<MAXSELECTIONS; slp++)
    {
    int x = selections[slp].x;
    int y = selections[slp].y;
    int w = selections[slp].w;
    int h = selections[slp].h;
 
    
    for (int elp=0; elp<EDGESIZE; elp++)
    {    
        for (int wlp=0; wlp<=w; wlp++)
        {
            setpixelbuf(pixels, x+wlp, y+elp, 0x00FFFFFF, true);
        }
    }
    for (int hlp=EDGESIZE; hlp<=(h-EDGESIZE); hlp++)
    {
        for (int elp=0; elp<EDGESIZE; elp++)
        {    
            setpixelbuf(pixels, x+elp, y+hlp, 0x00FFFFFF, true);
            setpixelbuf(pixels, x+w-elp, y+hlp, 0x00FFFFFF, true);
        }
    }
    for (int elp=0; elp<EDGESIZE; elp++)
    {    
        for (int wlp=0; wlp<=w; wlp++)
        {
            setpixelbuf(pixels, x+wlp, y+h-elp, 0x00FFFFFF, true);
        }
    }
    }
}

void fgTilesHilightedToPixelBuf(int priorityLevel)
{
     int tilex, tiley;
     int destx, desty;
     int destxprev, destyprev;
     int tilexprev, tileyprev;
          
     long colorBuf[4][16];
     for (int line=0; line<4; line++)
     {
         for (int color=0; color<16; color++)
         {
             colorBuf[line][color]=palColor2RGB(getfcRam(line,color));
         }
     }
     
     for (int y=0; y<THEIGHT; y++)
     {
         tiley=(y*8);
         
         for (int x=0; x<TWIDTH; x++)
         {  
                tilex=x*8;
                               
                for( int ylp = 0, ry = 7; ylp < 8; ylp++, ry-- ) 
                { 
                     
                    signed short hscrollpixoffset=((hScrollTable[((tiley+ylp))]&0xFFFF0000)>>16) & 0x7;
                    signed short hscrolltileoffset=(((hScrollTable[((tiley+ylp))]&0xFFFF0000)>>16) & 0x3F8)>>3;
                    signed short vscrollpixoffset=((vScrollRam[0] & 0xFFFF0000) >> 16) & 0x7;
                    signed short vscrolltileoffset=(((vScrollRam[0] & 0xFFFF0000) >> 16) & 0x3F8)>>3;
                    
                    signed short xIndexWithScroll = (x + hscrolltileoffset);
                    xIndexWithScroll = xIndexWithScroll % TWIDTH;
                    signed short yIndexWithScroll = (y + vscrolltileoffset);
                    yIndexWithScroll = yIndexWithScroll % THEIGHT;

                    word fgRamIndex=(xIndexWithScroll)+(yIndexWithScroll*TWIDTH);
                    hscrollpixoffset=-hscrollpixoffset;
                    vscrollpixoffset=-vscrollpixoffset;
                    
                    word fgRamVal=fgRam[fgRamIndex];
               
                    word flipx=(fgRamVal&0x800)>>11;
                    word flipy=(fgRamVal&0x1000)>>12;
                    word line=(fgRamVal&0x6000)>>13;
                    word priority=(fgRamVal&0x8000)>>15;
                    
                    if ( (priorityLevel == 0) ||
                    ((priorityLevel == 1) && (priority == 1)) || 
                    ((priorityLevel == 2) && (priority == 0)))
                    { 
                                    
                    word tileindex=(fgRamVal&0x7FF);

                    long vRamOffset=((tileindex)*16);
                  
                    for( int xlp = 0, rx = 7; xlp < 8; xlp++, rx-- ) 
                    { 
                         if (ylp == 0)
                         {
                            desty=tiley+ylp+(vscrollpixoffset);
                            destx=tilex+xlp+(hscrollpixoffset);
                            if (desty>0&&destx>0&&destx<960&&desty<720)
                                setpixelbuf(pixels, destx, desty, 0xFFFFFF, true);
                         }
                         else if (xlp == 7)
                         {
                            desty=tiley+ylp+(vscrollpixoffset);
                            destx=tilex+xlp+(hscrollpixoffset);
                            if (desty>0&&destx>0&&destx<960&&desty<720)
                                setpixelbuf(pixels, destx, desty, 0xFFFFFF, true);
                         }
                         else
                         {              
           
                            //Go through rows 
                            byte curnyb = 3-(xlp%4);
                            byte nybshift = (4*curnyb);
                            word curnybVal = (0xF)<<nybshift;
                            
                            //Get pixel 
                            word pixel = (vRam[vRamOffset+(xlp/4)+(ylp*2)] & curnybVal)>>nybshift;
                                
                            //Copy pixel 
                            if( ( flipy==1 ) && ( flipx==1 ) )
                            {
                                desty=tiley+ry+(vscrollpixoffset);
                                destx=tilex+rx+(hscrollpixoffset);
                                
                                if (desty>=0&&destx>=0&&destx<=960&&desty<=720 && ((pixel&0x000F)!=0))
                                {
                                   setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);
                                }
                            }
                            else 
                            {
                                 if( flipx==1 ) 
                                 {
                                     desty=tiley+ylp+(vscrollpixoffset);
                                     destx=tilex+rx+(hscrollpixoffset);
                                     if (desty>0&&destx>0&&destx<960&&desty<720 && ((pixel&0x000F)!=0))
                                     {
                                         setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);
                                     }
                                 }
                                 else if( flipy==1 )
                                 { 
                                     desty=tiley+ry+(vscrollpixoffset);
                                     destx=tilex+xlp+(hscrollpixoffset);
                                     if (desty>=0&&destx>=0&&destx<=960&&desty<=720 && ((pixel&0x000F)!=0))
                                     {
                                         setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);
                                    }
                                 }
                                 else
                                 { 
                                     desty=tiley+ylp+(vscrollpixoffset);
                                     destx=tilex+xlp+(hscrollpixoffset);
                                     if (desty>=0&&destx>=0&&destx<=960&&desty<=720 && ((pixel&0x000F)!=0))
                                     {
                                        setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);
                                     }
                                     
                                 }
                            }
                         }
                    }
                    }
                 }
                 
         }
     }  
               
}

void bgTilesHilightedToPixelBuf(int priorityLevel)
{

     int tilex, tiley;
     int destx, desty;
     int destxprev, destyprev;
     int tilexprev, tileyprev;
     
     long colorBuf[4][16];
     for (int line=0; line<4; line++)
     {
         for (int color=0; color<16; color++)
         {
             colorBuf[line][color]=palColor2RGB(getfcRam(line,color));
         }
     }
     
     //for (int y=0; y<THEIGHT; y++)
     for (int y=0; y<THEIGHT; y++)
     {         tiley=(y*8);

         for (int x=0; x<TWIDTH; x++)
         {                  tilex=x*8;
                                for( int ylp = 0, ry = 7; ylp < 8; ylp++, ry-- ) 
                { 

                    signed short vscrolloffset = vScrollRam[0] & 0x0000FFFF;
                    signed short vscrollpixoffset = vscrolloffset & 0x7;
                    signed short vscrolltileoffset = (vscrolloffset & 0x3F8) >> 3;
                    int hscrollindex = tiley + ylp - (vscrollpixoffset);
 
                    signed short hscrolloffset = (hScrollTable[hscrollindex] & 0x0000FFFF);
                    //hscrolloffset = hscrolloffset % 512;                                      //scroll value will wrap after 512
                    //hscrolloffset = hscrolloffset % -512;
                    signed short hscrollpixoffset=hscrolloffset & 0x7;                        //then grab pixel offset
                    signed short hscrolltileoffset=(hscrolloffset & 0x3F8)>>3;                //and tile offset individually
                    
                    signed short xIndexWithScroll;
                    if (hscrolloffset >= 0)
                    {
                        //hscrollpixoffset = -hscrollpixoffset;
                        xIndexWithScroll = (x - hscrolltileoffset) + (TWIDTH*2);
                    }
                    if (hscrolloffset < 0)
                    {
                        hscrollpixoffset = -(8-hscrollpixoffset);
                        xIndexWithScroll = (x - hscrolltileoffset - 1) + (TWIDTH*2);
                    }
                    xIndexWithScroll = xIndexWithScroll % TWIDTH;

                    signed short yIndexWithScroll = (y + vscrolltileoffset);
                    yIndexWithScroll = yIndexWithScroll % THEIGHT;

                    word bgRamIndex=(xIndexWithScroll)+(yIndexWithScroll*TWIDTH);
                    
                    vscrollpixoffset=-vscrollpixoffset;
                    
                    word bgRamVal=bgRam[bgRamIndex];
               
                    word flipx=(bgRamVal&0x800)>>11;
                    word flipy=(bgRamVal&0x1000)>>12;
                    word line=(bgRamVal&0x6000)>>13;
                    word priority=(bgRamVal&0x8000)>>15;
               
                    if ( (priorityLevel == 0) ||
                    ((priorityLevel == 1) && (priority == 1)) || 
                    ((priorityLevel == 2) && (priority == 0)))
                    { 
                    word tileindex=(bgRamVal&0x7FF);
                    
                    long vRamOffset=((tileindex)*16);
                    
                    for( int xlp = 0, rx = 7; xlp < 8; xlp++, rx-- ) 
                    { 
                         //Go through rows 
                         if (ylp == 0)
                         {
                            desty=tiley+ylp+(vscrollpixoffset);
                            destx=tilex+xlp+(hscrollpixoffset);
                            if (desty>0&&destx>0&&destx<960&&desty<720)
                                setpixelbuf(pixels, destx, desty, 0xFFFFFF, true);
                         }
                         else if (xlp == 7)
                         {
                            desty=tiley+ylp+(vscrollpixoffset);
                            destx=tilex+xlp+(hscrollpixoffset);
                            if (desty>0&&destx>0&&destx<960&&desty<720)
                                setpixelbuf(pixels, destx, desty, 0xFFFFFF, true);
                         }
                         else
                         {
                            //Get pixel 
                            byte curnyb = 3-(xlp%4);
                            byte nybshift = (4*curnyb);
                            word curnybVal = (0xF)<<nybshift;
                            
                            word pixel = (vRam[vRamOffset+(xlp/4)+(ylp*2)] & curnybVal)>>nybshift;
                                
                            //Copy pixel 
                            if( ( flipy==1 ) && ( flipx==1 ) )
                            {
                                desty=tiley+ry+(vscrollpixoffset);
                                destx=tilex+rx+(hscrollpixoffset);
                                setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);

                            }
                            else 
                            {
                                 if( flipx==1 ) 
                                 {
                                     desty=tiley+ylp+(vscrollpixoffset);
                                     destx=tilex+rx+(hscrollpixoffset);
                                     setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);

                                 }
                                 else if( flipy==1 )
                                 { 
                                     desty=tiley+ry+(vscrollpixoffset);
                                     destx=tilex+xlp+(hscrollpixoffset);
                                     setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);

                                 }
                                 else
                                 { 
                                     desty=tiley+ylp+(vscrollpixoffset);
                                     destx=tilex+xlp+(hscrollpixoffset);
                                     setpixelbuf(pixels, destx, desty, colorBuf[line][pixel&0x000F], true);

                                 }
                            }
                         }
                      }
                    }
                    }

         }
     }  
                 
}

void tileToPixelBuf(int tile, int tilex, int tiley, long *buf, int width, int height)
{
     
     int destx, desty;
          
     long colorBuf[4][16];
     for (int line=0; line<4; line++)
     {
         for (int color=0; color<16; color++)
         {
             colorBuf[line][color]=palColor2RGB(getfcRam(line,color));
         }
     }
          //tiley=(y*8);
     //tilex=x*8;
                
                
     for( int ylp = 0, ry = 7; ylp < 8; ylp++, ry-- ) 
     { 
         //signed short hscrollpixoffset=((hScrollTable[((tiley+ylp))]&0xFFFF0000)>>16) & 0x7;
         //signed short hscrolltileoffset=(((hScrollTable[((tiley+ylp))]&0xFFFF0000)>>16) & 0x3F8)>>3;
         //signed short vscrollpixoffset=((vScrollRam[0] & 0xFFFF0000) >> 16) & 0x7;
         //signed short vscrolltileoffset=(((vScrollRam[0] & 0xFFFF0000) >> 16) & 0x3F8)>>3;
         //signed short xIndexWithScroll = (x + hscrolltileoffset);
         //xIndexWithScroll = xIndexWithScroll % TWIDTH;
         //signed short yIndexWithScroll = (y + vscrolltileoffset);
         //yIndexWithScroll = yIndexWithScroll % THEIGHT;
         //hscrollpixoffset=-hscrollpixoffset;
         //vscrollpixoffset=-vscrollpixoffset;
        
         //word fgRamIndex=(xIndexWithScroll)+(yIndexWithScroll*TWIDTH);         
         //not using fgRam as a map to draw tiles, just drawing a specific tile by itself
         //word fgRamVal=fgRam[fgRamIndex];
  
         word flipx=(tile&0x800)>>11;
         word flipy=(tile&0x1000)>>12;
         word line=(tile&0x6000)>>13;
         word priority=(tile&0x8000)>>15;
               
         word tileindex=(tile&0x7FF);
         long vRamOffset=((tileindex)*16);
                   
         for (int xlp = 0, rx = 7; xlp < 8; xlp++, rx--) 
         { 
             //Go through rows 

             //Get pixel 
             byte curnyb = 3-(xlp%4);
             byte nybshift = (4*curnyb);
             word curnybVal = (0xF)<<nybshift;
                            
             word pixel = (vRam[vRamOffset+(xlp/4)+(ylp*2)] & curnybVal)>>nybshift;
                                
             //Copy pixel 
             if( ( flipy==1 ) && ( flipx==1 ) )
             {
                 desty=tiley+ry;  /*+(vscrollpixoffset);*/
                 destx=tilex+rx;  /*+(hscrollpixoffset);*/
                                
                 if (desty>=0&&destx>=0&&destx<=960&&desty<=720 && ((pixel&0x000F)!=0))
                 {
                     setpixelbuf(buf, destx, desty, colorBuf[line][pixel&0x000F], width, height, true);
                 }             
             }
             else 
             {
                 if( flipx==1 ) 
                 {
                     desty=tiley+ylp; /*+(vscrollpixoffset);*/
                     destx=tilex+rx; /*+(hscrollpixoffset);*/
                     if (desty>0&&destx>0&&destx<960&&desty<720 && ((pixel&0x000F)!=0))
                     {
                         setpixelbuf(buf, destx, desty, colorBuf[line][pixel&0x000F], width, height, true);
                     }
                 }
                 else if( flipy==1 )
                 { 
                     desty=tiley+ry; /*+(vscrollpixoffset);*/
                     destx=tilex+xlp; /*+(hscrollpixoffset);*/
                     if (desty>=0&&destx>=0&&destx<=960&&desty<=720 && ((pixel&0x000F)!=0))
                     {
                         setpixelbuf(buf, destx, desty, colorBuf[line][pixel&0x000F], width, height, true);
                     }
                 }
                 else
                 { 
                     desty=tiley+ylp; /*+(vscrollpixoffset);*/
                     destx=tilex+xlp; /*+(hscrollpixoffset);*/
          
                     if (desty>=0&&destx>=0&&destx<=960&&desty<=720 && ((pixel&0x000F)!=0))
                     {
                         setpixelbuf(buf, destx, desty, colorBuf[line][pixel&0x000F], width, height, true);
                     }
                 }
             }
         }
     }               
}

void vRamToPixelBuf(int offset, int prevw, int prevh, int bufx, int bufy, long *buf, int width, int height)
{
    int tile = 0;
    for (int hloop=0; hloop<prevh; hloop++)
    {
        for (int wloop=0; wloop<prevw; wloop++)
        {
            int prevOffset = ((hloop)*prevw) + wloop;

            tile = prevOffset + offset;
            
            int tilex = bufx + (wloop*8);
            int tiley = bufy + (hloop*8);

            tileToPixelBuf(tile, tilex, tiley, buf, width, height);
        }
    }
}

signed long getHScroll(int row)
{
    return hScrollTable[row];
}

signed long getVScroll()
{
    return vScrollRam[0];
}
